home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1995 October / EnigmA AMIGA RUN 01 (1995)(G.R. Edizioni)(IT)[!][issue 1995-10][Aminet 7].iso / Aminet / comm / tcp / AmigaTCP.lha / AmigaTCP / src / main.c < prev    next >
C/C++ Source or Header  |  1989-06-24  |  19KB  |  969 lines

  1. /*
  2.  *  Amiga version changes are 
  3.  *
  4.  *  Copyright (c)1987
  5.  *  Louis A. Mamakos
  6.  *
  7.  *  For non-commercial use only.
  8.  */
  9.  
  10. /* Main network program - provides both client and server functions */
  11. #define    NSESSIONS    10    /* Maximum interactive client sessions */
  12. #define HOSTNAMELEN 32        /* changed from 16 by Bdale 860812 */
  13.  
  14. #ifndef    STARTUP
  15. #ifdef    AMIGA
  16. #define    STARTUP "s:net-sequence"
  17. #else
  18. #define    STARTUP    "/autoexec.net"    /* File to read startup commands from */
  19. #endif
  20. #endif
  21.  
  22. #include <stdio.h>
  23. #include "machdep.h"
  24. #include "mbuf.h"
  25. #include "netuser.h"
  26. #include "timer.h"
  27. #include "icmp.h"
  28. #include "iface.h"
  29. #include "ip.h"
  30. #include "tcp.h"
  31. #include "ftp.h"
  32. #include "telnet.h"
  33. #include "session.h"
  34. #include "cmdparse.h"
  35.  
  36. #ifdef    AMIGA
  37. #include "amiga.h"
  38. #else
  39. #include "pc.h"
  40. #endif
  41.  
  42. extern struct interface *ifaces;
  43. struct session sessions[NSESSIONS];
  44. struct session *current;
  45. extern char major_rev[], minor_rev[];
  46.  
  47. int mode;
  48. FILE *logfp;
  49.  
  50. #ifdef    TRACE
  51. #include "trace.h"
  52. int32 trace;
  53. #endif
  54.  
  55. char hostname[HOSTNAMELEN];    
  56. int32 aton();
  57. int16 lport = 1001;
  58. #ifdef    AMIGA
  59. char prompt[] = "\33[1;33mnet>\33[m ";    /* make it standout and stuff */
  60. #else
  61. char prompt[] = "net> ";
  62. #endif
  63. char nospace[] = "No space!!\r\n";    /* Generic malloc fail message */
  64. static char notval[] = "Not a valid TCB\r\n";
  65.  
  66. #ifndef    MSDOS            /* PC uses F-10 key always */
  67. static char escape = 0x1d;    /* default escape character is ^] */
  68. #endif
  69.  
  70. /* Command lookup and branch table */
  71. int go(),cmdmode(),dodigipeat(),
  72.     doipaddr(),dotelnet(),doexit(),doclose(),dohostname(),
  73.     doreset(),dotcpstat(),dotrace(),doescape(),dospeed(),dohelp(),
  74.     dowindow(),doroute(),doecho(),
  75.     dolog(),doipstat(),doicmpstat(),doetherstat(),memstat(),doarp(),
  76.     dosession(),doftp(),domss(),dostart(),dostop(),doattach(),
  77.     domycall(),dosmtptick(),doudpstat(),dottl(),dokiss(),dotcpkick(),
  78.     doeol();
  79.  
  80. #ifdef HAPN
  81. int    dohapnstat();
  82. #endif HAPN
  83. #ifdef AMIGADEVDRV
  84. int    DriverInit(), DriverShutdown(), CheckTcp();
  85. #endif
  86. static struct cmds cmds[] = {
  87.     /* The "go" command must be first */
  88.     "",        go,        0, NULLCHAR,    NULLCHAR,
  89.     "arp",        doarp,        0, NULLCHAR,    NULLCHAR,
  90.     "attach",    doattach,    2,
  91.         "attach <hardware> <hw specific options>", NULLCHAR,
  92.     "close",    doclose,    0, NULLCHAR,    NULLCHAR,
  93. #ifdef    AX25
  94.     "digipeat",    dodigipeat,    0, NULLCHAR,    NULLCHAR,
  95. #endif
  96. #ifdef AMIGADEVDRV
  97.     "checktcp",    CheckTcp,    0, NULLCHAR,    NULLCHAR,
  98.     "driver",    DriverInit,    0, NULLCHAR,    NULLCHAR,
  99.     "driveroff",    DriverShutdown,    0, NULLCHAR,    NULLCHAR,
  100. #endif
  101.     "echo",        doecho,        0, NULLCHAR,    NULLCHAR,   
  102.     "eol",        doeol,        0, NULLCHAR,
  103.         "eol options: unix, standard",
  104. #ifndef    MSDOS
  105.     "escape",    doescape,    0, NULLCHAR,    NULLCHAR,   
  106. #endif
  107. #ifdef    PC_EC
  108.     "etherstat",    doetherstat,    0, NULLCHAR,    NULLCHAR,
  109. #endif  PC_EC
  110.     "exit",        doexit,        0, NULLCHAR,    NULLCHAR,
  111.     "ftp",        doftp,        2, "ftp <address>",    NULLCHAR,
  112. #ifdef HAPN
  113.     "hapnstat",    dohapnstat,    0, NULLCHAR,    NULLCHAR,
  114. #endif HAPN
  115.     "help",        dohelp,        0, NULLCHAR,    NULLCHAR,
  116.     "hostname",    dohostname,    0, NULLCHAR,    NULLCHAR,
  117.     "log",        dolog,        0, NULLCHAR,    NULLCHAR,
  118.     "icmpstat",    doicmpstat,    0, NULLCHAR,    NULLCHAR,
  119.     "ipaddr",    doipaddr,    0, NULLCHAR,    NULLCHAR,
  120.     "ipstat",    doipstat,    0, NULLCHAR,    NULLCHAR,
  121. #ifdef    AX25
  122.     "kiss",        dokiss,        0, NULLCHAR,    NULLCHAR,
  123. #endif
  124.     "smtp",        dosmtptick,    0, NULLCHAR,    NULLCHAR,
  125. #ifndef    AMIGA
  126.     "memstat",    memstat,    0, NULLCHAR,    NULLCHAR,
  127. #endif
  128.     "mss",        domss,        0, NULLCHAR,    NULLCHAR,
  129. #ifdef    AX25
  130.     "mycall",    domycall,    0, NULLCHAR,    NULLCHAR,
  131. #endif
  132.     "reset",    doreset,    0, NULLCHAR,    NULLCHAR,
  133.     "route",    doroute,    0, NULLCHAR,    NULLCHAR,
  134.     "session",    dosession,    0, NULLCHAR,    NULLCHAR,
  135.     "speed",    dospeed,    0, NULLCHAR,    NULLCHAR,
  136. #ifdef    SERVERS
  137.     "start",    dostart,    2, "start <servername>",NULLCHAR,
  138.     "stop",        dostop,        2, "stop <servername>",    NULLCHAR,
  139. #endif
  140.     "tcpstat",    dotcpstat,    0, NULLCHAR,    NULLCHAR,
  141.     "tcpkick",    dotcpkick,    0, NULLCHAR,    NULLCHAR,
  142.     "telnet",    dotelnet,    2, "telnet <address>",    NULLCHAR,
  143.     "trace",    dotrace,    0, NULLCHAR,    NULLCHAR,
  144.     "ttl",        dottl,        0, NULLCHAR,    NULLCHAR,
  145.     "udpstat",    doudpstat,    0, NULLCHAR,    NULLCHAR,
  146.     "window",    dowindow,    0, NULLCHAR,    NULLCHAR,
  147.     "?",        dohelp,        0, NULLCHAR,    NULLCHAR,
  148.     NULLCHAR,    NULLFP,        0,
  149.         "Unknown command; type \"?\" for list",   NULLCHAR, 
  150. };
  151.  
  152. /* "route" subcommands */
  153. int doadd(),dodrop();
  154. static struct cmds rtcmds[] = {
  155.     "add", doadd, 3,
  156.     "route add <dest addr>[/<bits>] <if name> [gateway] [metric]",
  157.     "Add failed",
  158.  
  159.     "drop", dodrop, 2,
  160.     "route drop <dest addr>[/<bits>]",
  161.     "Not in table",
  162.  
  163.     NULLCHAR, NULLFP, 0,
  164.     "route subcommands: add, drop",
  165.     NULLCHAR, 
  166. };
  167.  
  168. #ifdef    SERVERS
  169. /* "start" and "stop" subcommands */
  170. int ftp_start(),smtp_start(),discard_start(),echo_start(),telnet_start();
  171. static struct cmds startcmds[] = {
  172.     "discard",    discard_start,    0, NULLCHAR, NULLCHAR,
  173.     "echo",        echo_start,    0, NULLCHAR, NULLCHAR,
  174.     "ftp",        ftp_start,    0, NULLCHAR, NULLCHAR,
  175.     "smtp",        smtp_start,    0, NULLCHAR, NULLCHAR,
  176.     "telnet",    telnet_start,    0, NULLCHAR, NULLCHAR,
  177.     NULLCHAR,    NULLFP,        0,
  178.         "start options: discard, echo, ftp, smtp, telnet", NULLCHAR,
  179. };
  180. int ftp_stop(),smtp_stop(),echo_stop(),discard_stop(),telnet_stop();
  181. static struct cmds stopcmds[] = {
  182.     "discard",    discard_stop,    0, NULLCHAR, NULLCHAR,
  183.     "echo",        echo_stop,    0, NULLCHAR, NULLCHAR,
  184.     "ftp",        ftp_stop,    0, NULLCHAR, NULLCHAR,
  185.     "smtp",        smtp_stop,    0, NULLCHAR, NULLCHAR,
  186.     "telnet",    telnet_stop,    0, NULLCHAR, NULLCHAR,
  187.     NULLCHAR,    NULLFP,        0,
  188.         "stop options: discard, echo, ftp, smtp, telnet",  NULLCHAR,
  189. };
  190. #endif
  191.  
  192. main(argc,argv)
  193. int argc;
  194. char *argv[];
  195. {
  196.     static char inbuf[BUFSIZ];    /* keep it off the stack */
  197.     int c;
  198.     char *ttybuf,*fgets();
  199.     int16 cnt;
  200.     int ttydriv();
  201.     int cmdparse();
  202.     void check_time();
  203.     FILE *fp;
  204.     struct interface *ifp;
  205. #ifdef    AMIGA
  206.     char    *startup = STARTUP;
  207. #endif
  208.  
  209.     ioinit();
  210.     printf("KA9Q Internet Protocol Package, v%s.%s\n",major_rev,minor_rev);
  211. #ifdef    AMIGA
  212.     if (argc > 1)
  213.         startup = argv[1];
  214.  
  215.     if((fp = fopen(startup,"r")) != NULLFILE){
  216.         while(fgets(inbuf,BUFSIZ,fp) != NULLCHAR){
  217.             printf(prompt); printf(inbuf);
  218.             cmdparse(cmds, inbuf);
  219.         }
  220.         fclose(fp);
  221.     } else
  222.         printf("Can't read inital commands from %s\n", startup);
  223. #else
  224.     if((fp = fopen(STARTUP,"r")) != NULLFILE){
  225.         while(fgets(inbuf,BUFSIZ,fp) != NULLCHAR){
  226.             cmdparse(cmds,inbuf);
  227.         }
  228.         fclose(fp);
  229.     }        
  230. #endif
  231.     cmdmode();
  232.     smtpclinit();            /* arm SMTP background client timer */
  233.  
  234.     /* Main commutator loop */
  235.     for(;;){
  236.         /* Process any keyboard input */
  237.         while((c = kbread()) != -1){
  238. #ifdef    MSDOS
  239.             /* c == -2 means the command escape key (F10) */
  240.             if(c == -2){
  241.                 if(mode != CMD_MODE){
  242.                     printf("\r\n");
  243.                     cmdmode();
  244.                 }
  245.                 continue;
  246.             }
  247. #else
  248.             if(c == escape && escape != 0 && mode != CMD_MODE) {
  249.                 printf("\r\n");
  250.                 cmdmode();
  251.                 continue;
  252.             }
  253. #endif
  254.             if((cnt = ttydriv(c,&ttybuf)) == 0)
  255.                 continue;
  256.             switch(mode){
  257.             case CMD_MODE:
  258.                 (void)cmdparse(cmds,ttybuf);
  259.                 fflush(stdout);
  260.                 break;
  261.             case CONV_MODE:
  262. #ifndef    MSDOS
  263.                 if(ttybuf[0] == escape && escape != 0){
  264.                     printf("\r\n");
  265.                     cmdmode();
  266.                 } else
  267. #endif MSDOS
  268.                     if(current->parse != NULLFP)
  269.                         (*current->parse)(ttybuf,cnt);
  270.  
  271.                 break;
  272.             }
  273.             if(mode == CMD_MODE){
  274.                 printf(prompt);
  275.                 fflush(stdout);
  276.             }
  277.         }
  278.         /* Service the interfaces */
  279.         for(ifp = ifaces; ifp != NULLIF; ifp = ifp->next){
  280.             if(ifp->recv != NULLFP)
  281.                 (*ifp->recv)(ifp);
  282.         }
  283.  
  284.         /* Service the clock if it has ticked */
  285.         check_time();
  286. #ifdef AMIGADEVDRV
  287.         /* check device driver open request */
  288.         check_driver();
  289.         CheckTcp();
  290. #else
  291. #ifdef    MSDOS
  292.         /* Tell DoubleDos to let the other task run for awhile.
  293.          * If DoubleDos isn't active, this is a no-op
  294.          */
  295.         giveup();
  296. #else
  297.         /* Wait until interrupt, then do it all over again */
  298.         eihalt();
  299. #endif
  300. #endif AMIGADEVDRV
  301.     }
  302. }
  303.  
  304. /* Enter command mode */
  305. int
  306. cmdmode()
  307. {
  308.     if(mode != CMD_MODE){
  309.         mode = CMD_MODE;
  310.         cooked();
  311.         printf(prompt);
  312.         fflush(stdout);
  313.     }
  314.     return 0;
  315. }
  316. /* Select and display sessions */
  317. static
  318. dosession(argc,argv)
  319. int argc;
  320. char *argv[];
  321. {
  322.     unsigned i;
  323.     struct session *s;
  324.     extern char *tcpstates[];
  325.     char *psocket();
  326.  
  327.     if(argc < 2){
  328.         printf(" #  Type    Remote socket          TCB  State\r\n");
  329.         for(s=sessions;s < & sessions[NSESSIONS];s++){
  330.             switch(s->type){
  331.             case TELNET:
  332. #ifndef    AMIGA
  333.                 printf("%c%-3d%Telnet  %-23s%4x %-s\r\n",
  334.                     (current == s)? '*':' ',
  335.                     s - sessions,
  336.                     psocket(&s->cb.telnet->tcb->conn.remote),
  337.                     (int)s->cb.telnet->tcb,
  338.                     tcpstates[s->cb.telnet->tcb->state]);
  339. #else
  340.                 printf("%c%-3d%Telnet  %-23s%6lx %-s\r\n",
  341.                     (current == s)? '*':' ',
  342.                     s - sessions,
  343.                     psocket(&s->cb.telnet->tcb->conn.remote),
  344.                     (unsigned long)s->cb.telnet->tcb,
  345.                     tcpstates[s->cb.telnet->tcb->state]);
  346. #endif                break;
  347.             case FTP:
  348. #ifndef    AMIGA
  349.                 printf("%c%-3d%FTP     %-23s%4x %-s\r\n",
  350.                     (current == s)? '*':' ',
  351.                     s - sessions,
  352.                     psocket(&s->cb.ftp->control->conn.remote),
  353.                     (int)s->cb.ftp->control,
  354.                     tcpstates[s->cb.ftp->control->state]);
  355. #else
  356.                 printf("%c%-3d%FTP     %-23s%6lx %-s\r\n",
  357.                     (current == s)? '*':' ',
  358.                     s - sessions,
  359.                     psocket(&s->cb.ftp->control->conn.remote),
  360.                     (unsigned long)s->cb.ftp->control,
  361.                     tcpstates[s->cb.ftp->control->state]);
  362. #endif
  363.                 break;
  364.             }
  365.         }
  366.         return 0;
  367.     }
  368.     i = atoi(argv[1]);
  369.     if(i > NSESSIONS){
  370.         printf("Invalid session: %d\r\n",i);
  371.         return 1;
  372.     }
  373.     if(sessions[i].type == FREE){
  374.         printf("Inactive session: %d\r\n",i);
  375.         return 1;
  376.     }
  377.     current = &sessions[i];
  378.     go();
  379.     return 0;
  380. }
  381. /* Enter conversational mode with current session */
  382. int
  383. go()
  384. {
  385.     void rcv_char(),r_ctl();
  386.  
  387.     if(current == NULLSESSION || current->type == FREE)
  388.         return 0;
  389.     mode = CONV_MODE;
  390.     switch(current->type){
  391.     case TELNET:
  392.         if(current->cb.telnet->remote[TN_ECHO])
  393.             raw();    /* Re-establish raw mode if it was set */
  394.         rcv_char(current->cb.telnet->tcb,0); /* Get any pending input */
  395.         break;
  396.     case FTP:
  397.         r_ctl(current->cb.ftp->control,0);
  398.         break;
  399.     }
  400.     return 0;
  401. }
  402. #ifdef    AX25
  403. extern int digipeat;
  404. dodigipeat(argc,argv)
  405. int argc;
  406. char *argv[];
  407. {
  408.     if(argc == 1) {
  409.         printf("digipeat %s\r\n",digipeat ? "on" : "off");
  410.     } else {
  411.         if(strcmp(argv[1],"on") == 0)
  412.             digipeat = 1;
  413.         else
  414.             digipeat = 0;
  415.     }
  416. }
  417. #endif
  418. static
  419. doipaddr(argc,argv)
  420. int argc;
  421. char *argv[];
  422. {
  423.     char *inet_ntoa();
  424.  
  425.     if(argc < 2)
  426.         printf("%s\r\n",inet_ntoa(ip_addr));
  427.     else
  428.         ip_addr = aton(argv[1]);
  429.     return 0;
  430. }
  431. static
  432. doexit(argc,argv)
  433. int argc;
  434. char *argv[];
  435. {
  436.     iostop();
  437.     DriverShutdown();
  438.     exit(0);
  439. }
  440. static
  441. doclose(argc,argv)
  442. int argc;
  443. char *argv[];
  444. {
  445.     if(current == NULLSESSION){
  446.         printf("No current session\r\n");
  447.         return 0;
  448.     }
  449.     switch(current->type){
  450.     case TELNET:
  451.         close_tcp(current->cb.telnet->tcb);
  452.         break;
  453.     case FTP:
  454.         close_tcp(current->cb.ftp->control);
  455.         break;
  456.     }
  457.     return 0;
  458. }
  459. static
  460. doreset(argc,argv)
  461. int argc;
  462. char *argv[];
  463. {
  464.     long htol();
  465.     struct tcb *tcb;
  466.  
  467.     if(argc < 2){
  468.         if(current == NULLSESSION){
  469.             printf("No current session\r\n");
  470.             return 1;
  471.         }
  472.         switch(current->type){
  473.         case TELNET:
  474.             tcb = current->cb.telnet->tcb;
  475.             break;
  476.         case FTP:
  477.             tcb = current->cb.ftp->control;
  478.             break;
  479.         }
  480.     } else
  481.         tcb = (struct tcb *)htol(argv[1]);
  482.     if(!tcpval(tcb)){
  483.         printf(notval);
  484.         return 1;
  485.     }
  486.     close_self(tcb,RESET);
  487.     return 0;
  488. }
  489. static
  490. int
  491. dotcpstat(argc,argv)
  492. int argc;
  493. char *argv[];
  494. {
  495.     long htol();
  496.     register struct tcb *tcb;
  497.  
  498.     if(argc < 2){
  499.         tcpstat();
  500.     } else {
  501.         tcb = (struct tcb *)htol(argv[1]);
  502.         if(tcpval(tcb))
  503.             state_tcp(tcb);
  504.         else
  505.             printf(notval);
  506.     }
  507.     return 0;
  508. }
  509. static
  510. int
  511. dotcpkick(argc,argv)
  512. int argc;
  513. char *argv[];
  514. {
  515.     long htol();
  516.     register struct tcb *tcb;
  517.     void tcp_timeout();
  518.  
  519.     if(argc < 2){
  520.         if(current == NULLSESSION){
  521.             printf("No current session\r\n");
  522.             return 1;
  523.         }
  524.         switch(current->type){
  525.         case TELNET:
  526.             tcb = current->cb.telnet->tcb;
  527.             break;
  528.         case FTP:
  529.             tcb = current->cb.ftp->control;
  530.             break;
  531.         }
  532.     } else
  533.         tcb = (struct tcb *)htol(argv[1]);
  534.  
  535.     if(!tcpval(tcb)){
  536.         printf(notval);
  537.         return 1;
  538.     }
  539.     if(argc > 2){
  540.         /* Optional value for SRTT */
  541.         tcb->srtt = atoi(argv[2]);
  542.     }
  543.     /* Don't actually do anything unless something is pending */
  544.     if(tcb->sndcnt != 0){
  545.         tcb->retry = 0;
  546.         tcp_timeout((int *)tcb);
  547.     }
  548.     return 0;
  549. }
  550. static
  551. int
  552. dotrace(argc,argv)
  553. int argc;
  554. char *argv[];
  555. {
  556.     long htol();
  557. #ifdef TRACE
  558.     if(argc < 2)
  559.         printf("trace level 0x%08lx\r\n",trace);
  560.     else
  561.         trace = htol(argv[1]);
  562.     return 0;
  563. #else
  564.     printf("Trace not enabled - recompile with TRACE defined\r\n");
  565. #endif
  566. }
  567. static
  568. dohostname(argc,argv)
  569. int argc;
  570. char *argv[];
  571. {
  572.     char *strncpy();
  573.  
  574.     if(argc < 2)
  575.         printf("%s\r\n",hostname);
  576.     else 
  577.         strncpy(hostname,argv[1],HOSTNAMELEN);
  578.     return 0;
  579. }
  580. static
  581. int
  582. dolog(argc,argv)
  583. int argc;
  584. char *argv[];
  585. {
  586.     char *strncpy();
  587.  
  588. #ifdef    AMIGA
  589.     static char logname[45];  /* long enough for CON:10/10/300/300/title */
  590. #else
  591.     static char logname[15];
  592. #endif
  593.     if(argc < 2){
  594.         if(logfp)
  595.             printf("Logging to %s\r\n",logname);
  596.         else
  597.             printf("Logging off\r\n");
  598.         return 0;
  599.     }
  600.     if(logfp){
  601.         fclose(logfp);
  602.         logfp = NULLFILE;
  603.     }
  604.     if(strcmp(argv[1],"stop") != 0){
  605. #ifdef    AMIGA
  606.         strncpy(logname,argv[1],45);
  607. #else
  608.         strncpy(logname,argv[1],15);
  609. #endif
  610.         logfp = fopen(logname,"a+");
  611.     }
  612.     return 0;
  613. }
  614. #ifndef    MSDOS
  615. static
  616. int
  617. doescape(argc,argv)
  618. int argc;
  619. char *argv[];
  620. {
  621.     if(argc < 2)
  622.         printf("0x%x\r\n",escape);
  623.     else 
  624.         escape = *argv[1];
  625.     return 0;
  626. }
  627. #endif    MSDOS
  628. static
  629. int
  630. dohelp(argc,argv)
  631. int argc;
  632. char *argv[];
  633. {
  634.     register struct cmds *cmdp;
  635.     int i,j;
  636.  
  637.     printf("Main commands:\r\n");
  638.     for(i=0,cmdp = cmds;cmdp->name != NULL;cmdp++,i++){
  639.         printf("%s",cmdp->name);
  640.         if((i % 4) == 3)
  641.             printf("\r\n");
  642.         else {
  643.             for(j=strlen(cmdp->name);j < 16; j++)
  644.                 putchar(' ');
  645.         }
  646.     }
  647.     if((i % 4) != 0)
  648.         printf("\r\n");
  649.     return 0;
  650. }
  651. static
  652. int
  653. domss(argc,argv)
  654. int argc;
  655. char *argv[];
  656. {
  657.     if(argc < 2)
  658.         printf("%d\r\n",tcp_mss);
  659.     else
  660.         tcp_mss = atoi(argv[1]);
  661.     return 0;
  662. }
  663. static
  664. int
  665. dowindow(argc,argv)
  666. int argc;
  667. char *argv[];
  668. {
  669.     if(argc < 2)
  670.         printf("%d\r\n",tcp_window);
  671.     else
  672.         tcp_window = atoi(argv[1]);
  673.     return 0;
  674. }
  675. static
  676. int
  677. dottl(argc,argv)
  678. char *argv[];
  679. {
  680.     if(argc < 2)
  681.         printf("%u\r\n",ip_ttl & 0xff);
  682.     else
  683.         ip_ttl = atoi(argv[1]);
  684.     return 0;
  685. }
  686. struct session *
  687. newsession()
  688. {
  689.     register int i;
  690.  
  691.     for(i=0;i<NSESSIONS;i++)
  692.         if(sessions[i].type == FREE)
  693.             return &sessions[i];
  694.     return NULLSESSION;
  695. }
  696. freesession(s)
  697. struct session *s;
  698. {
  699.     if(s != NULLSESSION)
  700.         s->type = FREE;
  701. }
  702. /* Display and/or manipulate routing table */
  703. int
  704. doroute(argc,argv)
  705. int argc;
  706. char *argv[];
  707. {
  708.     if(argc < 2){
  709.         dumproute();
  710.         return 0;
  711.     }
  712.     return subcmd(rtcmds,argc,argv);
  713. }
  714. /* Add an entry to the routing table
  715.  * E.g., "add 1.2.3.4 ax0 5.6.7.8 3"
  716.  */
  717. int
  718. doadd(argc,argv)
  719. int argc;
  720. char *argv[];
  721. {
  722.     struct interface *ifp;
  723.     int32 dest,gateway;
  724.     unsigned bits;
  725.     char *bitp,*index();
  726.     int metric;
  727.  
  728.     if(strcmp(argv[1],"default") == 0){
  729.         dest = 0;
  730.         bits = 0;
  731.     } else {
  732.         dest = aton(argv[1]);
  733.  
  734.         /* If IP address is followed by an optional slash and
  735.          * a length field, (e.g., 128.96/16) get it;
  736.          * otherwise assume a full 32-bit address
  737.          */
  738.         if((bitp = index(argv[1],'/')) != NULLCHAR){
  739.             bitp++;
  740.             bits = atoi(bitp);
  741.         } else
  742.             bits = 32;
  743.     }
  744.     for(ifp=ifaces;ifp != NULLIF;ifp = ifp->next){
  745.         if(strcmp(argv[2],ifp->name) == 0)
  746.             break;
  747.     }
  748.     if(ifp == NULL){
  749.         printf("Interface \"%s\" unknown\r\n",argv[2]);
  750.         return 1;
  751.     }
  752.     if(argc > 3)
  753.         gateway = aton(argv[3]);
  754.     else
  755.         gateway = 0;
  756.  
  757.     if(argc > 4)
  758.         metric = atoi(argv[4]);
  759.     else
  760.         metric = 0;
  761.  
  762.     rt_add(dest,bits,gateway,metric,ifp);
  763.     return 0;
  764. }
  765. /* Drop an entry from the routing table
  766.  * E.g., "drop 128.96/16
  767.  */
  768. int
  769. dodrop(argc,argv)
  770. int argc;
  771. char *argv[];
  772. {
  773.     char *bitp,*index();
  774.     unsigned bits;
  775.  
  776.     /* If IP address is followed by an optional slash and length field,
  777.      * (e.g., 128.96/16) get it; otherwise assume a full 32-bit address
  778.      */
  779.     if((bitp = index(argv[1],'/')) != NULLCHAR){
  780.         bitp++;
  781.         bits = atoi(bitp);
  782.     } else
  783.         bits = 32;
  784.  
  785.     return rt_drop(aton(argv[1]),bits);
  786. }
  787.  
  788. #ifdef SERVERS
  789. dostart(argc,argv)
  790. int argc;
  791. char *argv[];
  792. {
  793.     return subcmd(startcmds,argc,argv);
  794. }
  795. dostop(argc,argv)
  796. int argc;
  797. char *argv[];
  798. {
  799.     return subcmd(stopcmds,argc,argv);
  800. }
  801. #endif SERVERS
  802.  
  803. doecho(argc,argv)
  804. int argc;
  805. char *argv[];
  806. {
  807.     extern int refuse_echo;
  808.  
  809.     if(argc < 2){
  810.         if(refuse_echo)
  811.             printf("Refuse\r\n");
  812.         else
  813.             printf("Accept\r\n");
  814.     } else {
  815.         if(strcmp(argv[1],"refuse") == 0)
  816.             refuse_echo = 1;
  817.         else if(strcmp(argv[1],"accept") == 0)
  818.             refuse_echo = 0;
  819.         else
  820.             return -1;
  821.     }
  822.     return 0;
  823. }
  824. /* set for unix end of line for remote echo mode telnet */
  825. doeol(argc,argv)
  826. int argc;
  827. char *argv[];
  828. {
  829.     extern int unix_line_mode;
  830.  
  831.     if(argc < 2){
  832.         if(unix_line_mode)
  833.             printf("Unix\r\n");
  834.         else
  835.             printf("Standard\r\n");
  836.     } else {
  837.         if(strcmp(argv[1],"unix") == 0)
  838.             unix_line_mode = 1;
  839.         else if(strcmp(argv[1],"standard") == 0)
  840.             unix_line_mode = 0;
  841.         else {
  842.             return -1;
  843.         }
  844.     }
  845.     return 0;
  846. }
  847. /* List of supported hardware devices */
  848. #ifdef    PC_EC
  849. int ec_attach();
  850. #endif
  851.  
  852. int asy_attach();
  853.  
  854. #ifdef    PC100
  855. int pc_attach();
  856. #endif
  857.  
  858. #ifdef HAPN
  859. int hapn_attach();
  860. #endif
  861.  
  862. #ifdef    NETROM
  863. int netrom_attach();
  864. #endif
  865.  
  866. struct cmds attab[] = {
  867. #ifdef    NETROM
  868.     /* NET/ROM virtual interface using companion asy interface in AX.25 mode */
  869.     "netrom", netrom_attach, 4,
  870.     "attach netrom <asy-intf> ax25 <label> [mtu [ upd-freq ]]",
  871.     "Could not attach NET/ROM virtual interface",
  872. #endif
  873. #ifdef    PC_EC
  874.     /* 3-Com Ethernet interface */
  875.     "3c500", ec_attach, 7, 
  876.     "attach 3c500 <address> <vector> arpa <label> <buffers> <mtu>",
  877.     "Could not attach 3c500",
  878. #endif
  879.     /* Ordinary PC asynchronous adaptor */
  880.     "asy", asy_attach, 8, 
  881.     "attach asy <address> <vector> slip|ax25 <label> <buffers> <mtu> <speed>",
  882.     "Could not attach asy",
  883. #ifdef    PC100
  884.     /* PACCOMM PC-100 8530 HDLC adaptor */
  885.     "pc100", pc_attach, 8, 
  886.     "attach pc100 <address> <vector> ax25 <label> <buffers> <mtu> <speed>",
  887.     "Could not attach pc100",
  888. #endif
  889. #ifdef    HAPN
  890.     /* Hamilton Area Packet Radio (HAPN) 8273 HDLC adaptor */
  891.     "hapn", hapn_attach, 8,
  892.     "attach hapn <address> <vector> ax25 <label> <rx bufsize> <mtu> csma|full",
  893.     "Could not attach hapn",
  894. #endif
  895.     NULLCHAR, NULLFP, 0,
  896.     "Unknown device",
  897.     NULLCHAR,
  898. };
  899.  
  900. /* Attach an interface
  901.  * Syntax: attach <hw type> <I/O address> <vector> <mode> <label> <bufsize> [<speed>]
  902.  */
  903. doattach(argc,argv)
  904. int argc;
  905. char *argv[];
  906. {
  907.     return subcmd(attab,argc,argv);
  908. }
  909. int
  910. dospeed(argc,argv)
  911. int argc;
  912. char *argv[];
  913. {
  914.     int i;
  915.  
  916.     if(argc < 3){
  917.         for(i=0;i < nasy; i++){
  918.             printf("%d: %d bps\r\n",i,asy[i].speed);
  919.         }
  920.         return 0;
  921.     }
  922.     i = atoi(argv[1]);
  923.     if(i >= nasy){
  924.         printf("Line %d out of range\r\n",i);
  925.         return 0;
  926.     }
  927.     asy_speed(i,atoi(argv[2]));
  928.     return i;
  929. }
  930.  
  931. /* Log messages of the form
  932.  * Tue Jan 31 00:00:00 1987 44.64.0.7:1003 open FTP
  933.  */
  934. /*VARARGS2*/
  935. log(tcb,fmt,arg1,arg2,arg3,arg4)
  936. struct tcb *tcb;
  937. char *fmt;
  938. int arg1,arg2,arg3,arg4;
  939. {
  940.     char *cp,*cp1,*ctime(),*index();
  941.     long t;
  942.  
  943.     if(logfp == NULLFILE)
  944.         return;
  945.     time(&t);
  946.     cp = ctime(&t);
  947.     if((cp1 = index(cp,'\n')) != NULLCHAR)
  948.         *cp1 = '\0';
  949.     fprintf(logfp,"%s %s - ",cp,psocket(&tcb->conn.remote));
  950.     fprintf(logfp,fmt,arg1,arg2,arg3,arg4);
  951.     fprintf(logfp,"\n");
  952.     fflush(logfp);
  953. }
  954. /* Define null definitions for unused interfaces to avoid pulling in code
  955.  * from the library
  956.  */
  957. #ifndef    ETHER
  958. int ec_output() {}
  959. int pether() {}
  960. int gether() {}
  961. char *ether_bdcst = NULLCHAR;
  962. #endif ETHER
  963.  
  964. #ifndef AX25
  965. int setcall() {}
  966. int psax25() {}
  967. struct ax25_addr ax25_bdcst,mycall;
  968. #endif AX25
  969.